#include "pch.hpp"
#include "Widget.hpp"

using namespace Engine;
using namespace Engine::Ui;




Widget::Widget(BasicStyleDefinition::ptr styleDefinition)
	: m_styleDefinition(styleDefinition)

	// Red color used as default to make bugs more visible
	, m_backgroundColor(1, 0, 0, 1)

	, m_rect(rect::point(0, 0))
	, m_minimumSize(0, 0)
	, m_maximumSize(std::numeric_limits<int>::max(), std::numeric_limits<int>::max())

	, m_visible(true)
	, m_resizingType(Resizing::Standard)
	, m_resizing(false)
	, m_mouseHovered(false)
	, m_mousePressed(false)
	, m_widgetState(WidgetState::Normal)

	, stateChanged(m_stateChanged)
	, mouseEnter(m_mouseEnter)
	, mouseLeave(m_mouseLeave)
	, mouseClicked(m_mouseClicked)
	, mouseDblClicked(m_mouseDblClicked)
	, moved(m_moved)
	, resized(m_resized)
	, destroyed(m_destroyed)
	, addWidget(m_add)
	, removeWidget(m_remove)
{
	stateChanged.connect(notify::slot_type(&Widget::onStateChanged, this, _1));
}
///////////////////////////////////////////////////////////////////////////////////////////////////

Widget::Widget(Widget::weak_ptr parent)
	: m_styleDefinition(ptr(parent)->styleDefinition())

	, m_parent(parent)

	// Red color used as default to make bugs more visible
	, m_backgroundColor(1, 0, 0, 1)

	, m_rect(rect::point(0, 0))
	, m_minimumSize(0, 0)
	, m_maximumSize(std::numeric_limits<int>::max(), std::numeric_limits<int>::max())

	, m_visible(true)
	, m_resizingType(Resizing::Standard)
	, m_resizing(false)
	, m_mouseHovered(false)
	, m_mousePressed(false)
	, m_widgetState(WidgetState::Normal)

	, stateChanged(m_stateChanged)
	, mouseEnter(m_mouseEnter)
	, mouseLeave(m_mouseLeave)
	, mouseClicked(m_mouseClicked)
	, mouseDblClicked(m_mouseDblClicked)
	, moved(m_moved)
	, resized(m_resized)
	, destroyed(m_destroyed)
	, addWidget(m_add)
	, removeWidget(m_remove)
{
	stateChanged.connect(notify::slot_type(&Widget::onStateChanged, this, _1));
}
///////////////////////////////////////////////////////////////////////////////////////////////////

void Widget::post_create(Widget::ptr _this)
{
	// First of all, we wanna store a weak_ptr to this instance
	m_this = _this;

	// Since our widget is fully constructed we know the actual type and can retrieve
	// all style information
	createStyleId(m_styleId, StyleIdentifier("*", type()));

	// Last but not least, the widgets style, size, etc... is retrieved from the style
	updateStyle();
}
///////////////////////////////////////////////////////////////////////////////////////////////////




Widget::~Widget()
{
	m_destroyed(m_this);
}
///////////////////////////////////////////////////////////////////////////////////////////////////




const WidgetStyleIdentifier& Widget::styleId() const
{
	return m_styleId;
}
///////////////////////////////////////////////////////////////////////////////////////////////////

void Widget::createStyleId(WidgetStyleIdentifier& styleId, StyleIdentifier widgetStyle) const
{
	if(widgetStyle.isEmpty())
		widgetStyle = StyleIdentifier::default_(type());

	styleId.clear();
	styleId.resize(numParents() + 1);
	styleId[0] = widgetStyle;

	// A WidgetStyleIdentifier consists of a description of each widget
	// in the hierarchy list (ie. this widget and all parents).
	// Now it's time to retrieve information about the parent
	auto parent = m_parent.lock();
	if(parent)
	{
		if(!parent->m_styleId.size())
			throw programming_error("The parent's style id is not allowed to be empty");

		// Now copy the entire styleId from the parent into this style id.
		// (While keeping the actual style for this widget)
		WidgetStyleIdentifier::iterator i = styleId.begin();
		std::advance(i, 1);
		std::copy(parent->m_styleId.begin(), parent->m_styleId.end(), i);
	}
}
///////////////////////////////////////////////////////////////////////////////////////////////////




Widget::weak_ptr Widget::weak_from_this()
{
	return m_this;
}
///////////////////////////////////////////////////////////////////////////////////////////////////

Widget::ptr Widget::shared_from_this()
{
	return ptr(m_this);
}
///////////////////////////////////////////////////////////////////////////////////////////////////

Widget::const_ptr Widget::shared_from_this() const
{
	return const_ptr(m_this);
}
///////////////////////////////////////////////////////////////////////////////////////////////////




Widgets::Type Widget::type() const
{
	return Widgets::Widget;
}
///////////////////////////////////////////////////////////////////////////////////////////////////

BasicStyleDefinition::ptr Widget::styleDefinition() const
{
	return m_styleDefinition;
}
///////////////////////////////////////////////////////////////////////////////////////////////////

WidgetStyle::ptr Widget::style() const
{
	return m_widgetStyle;
}
///////////////////////////////////////////////////////////////////////////////////////////////////

void Widget::setStyleDefinition(BasicStyleDefinition::ptr style)
{
	m_styleDefinition = style;

	WidgetIterator i(m_widgets);
	while(i.hasNext())
	{
		const Widget::ptr& child = i.next();
		child->setStyleDefinition(style);
	}

	updateStyle();
}
///////////////////////////////////////////////////////////////////////////////////////////////////

void Widget::setStyle(StyleIdentifier widgetId)
{
	// Now create a WidgetStyleId, a list of all styles from all parents
	createStyleId(m_styleId, widgetId);
	m_widgetStyle = m_styleDefinition->widgetStyle(m_styleId);

	foreach(const Widget::ptr& child, m_widgets)
	{
		child->updateStyle();
	}

	styleChanged();

	if(m_layout)
		m_layout->repositionChildren();
}
///////////////////////////////////////////////////////////////////////////////////////////////////

void Widget::updateStyle()
{
	StyleIdentifier styleId;
	if(!m_styleId.isEmpty()) styleId = m_styleId.front();
	else                     styleId.name = "*";
	styleId.type = type();

	setStyle(styleId);
}
///////////////////////////////////////////////////////////////////////////////////////////////////




Layout::ptr Widget::layout() const
{
	return m_layout;
}
///////////////////////////////////////////////////////////////////////////////////////////////////

const Layout::ptr& Widget::setLayout(const Layout::ptr& layout)
{
	m_layout = layout;
	return layout;
}
///////////////////////////////////////////////////////////////////////////////////////////////////




Widget::ptr Widget::parent() const
{
	return m_parent.lock();
}
///////////////////////////////////////////////////////////////////////////////////////////////////

const Widget::ptr& Widget::add(const Widget::ptr& widget)
{
	// A widget can only be added if we're its parent
	auto parent = widget->parent();
	if(parent && parent.get() != this)
		BOOSTEXT_THROW(exception("The given widget's parent is not this widget"));

	/*
	// The other widget has been fully constructed
	// Now is the time to tell it to request it's style from
	// the style document
	widget->updateStyle();
	*/

	m_widgets.push_front(widget);
	m_add(m_this, widget);

	widget->mouseClicked.connect(notify::slot_type(&Widget::onChildClicked, this, _1)
		.track(m_this)
		.track(widget)
	);

	return widget;
}
///////////////////////////////////////////////////////////////////////////////////////////////////

bool Widget::isChild(const Widget::ptr& widget) const
{
	if(isDirectChild(widget))
		return true;

	WidgetIterator i(m_widgets);
	while(i.hasNext())
	{
		const Widget::ptr& child = i.next();
		if(child->isChild(widget))
			return true;
	}

	return false;
}
///////////////////////////////////////////////////////////////////////////////////////////////////

bool Widget::isDirectChild(const Widget::ptr& widget) const
{
	return find(widget) != m_widgets.constEnd();
}
///////////////////////////////////////////////////////////////////////////////////////////////////

std::size_t Widget::numParents() const
{
	auto parent = m_parent.lock();
	std::size_t num = 0;
	while(parent)
	{
		++num;
		parent = parent->m_parent.lock();
	}

	return num;
}
///////////////////////////////////////////////////////////////////////////////////////////////////

void Widget::bringToTop()
{
	auto parent = m_parent.lock();
	if(parent)
	{
		parent->bringToTop(ptr(m_this));
	}
}
///////////////////////////////////////////////////////////////////////////////////////////////////

void Widget::bringToTop(weak_ptr widget)
{
	if(widget.expired())
		return;

	WidgetList::iterator i = find(widget.lock());
	if(i == m_widgets.end())
		BOOSTEXT_THROW(exception("Can't bring non-child widget to top"));

	m_widgets.erase(i);
	m_widgets.push_front(widget.lock());
}
///////////////////////////////////////////////////////////////////////////////////////////////////

/**
void Widget::remove(const Widget::ptr& widget)
{
	WidgetList::iterator i = find(widget);
	if(i == m_widgets.end())
		BOOSTEXT_THROW(exception("Can't remove non-child widget"));

	m_widgets.erase(i);
	m_remove(this, widget.get());

	widget->mouseClicked.disconnect(boost::bind(&Widget::onChildClicked, this, _1));
}
///////////////////////////////////////////////////////////////////////////////////////////////////
*/




int2 Widget::pos() const
{
	return m_rect.topLeft;
}
///////////////////////////////////////////////////////////////////////////////////////////////////

intsize2 Widget::size() const
{
	return m_rect.size();
}
///////////////////////////////////////////////////////////////////////////////////////////////////

math::rectangle<int> Widget::rect() const
{
	return m_rect;
}
///////////////////////////////////////////////////////////////////////////////////////////////////

int2 Widget::clientPos() const
{
	return m_rect.topLeft + padding().xy();
}
///////////////////////////////////////////////////////////////////////////////////////////////////

intsize2 Widget::clientSize() const
{
	int4 padd = padding();
	intsize2 size = m_rect.size();
	size.width -= padd.x + padd.z;
	size.height -= padd.y + padd.w;

	return size;
}
///////////////////////////////////////////////////////////////////////////////////////////////////

math::rectangle<int> Widget::clientRect() const
{
	int4 pad = padding();
	return math::rectangle<int>::corners(m_rect.topLeft + pad.xy(),
		m_rect.bottomRight - pad.zw());
}
///////////////////////////////////////////////////////////////////////////////////////////////////

intsize2 Widget::minimumSize() const
{
	if(m_layout)
	{
		// A widget can be configured to have a certain minimum size, however sometimes
		// children may simply require more space than that (because of their minimum size).
		// In order to not produce visual errors (like reporting the wrong minimum size
		// to the parent) we overwrite the configured minimum size by the size reported
		// from the style, in case the configured minimum size is smaller.
		int4 padd = padding();
		intsize2 minSize = m_layout->calculateMinimumSize() + intsize2(padd.x + padd.z, padd.y + padd.w);
		return math::max(minSize, configuredMinimumSize());
	}
	else
	{
		return configuredMinimumSize();
	}
}
///////////////////////////////////////////////////////////////////////////////////////////////////

intsize2 Widget::minimumClientSize() const
{
	int4 padd = padding();
	intsize2 minSize = minimumSize();

	minSize.width -= padd.x + padd.z;
	minSize.height -= padd.y + padd.w;

	return minSize;
}
///////////////////////////////////////////////////////////////////////////////////////////////////

intsize2 Widget::configuredMinimumSize() const
{
	return m_minimumSize;
}
///////////////////////////////////////////////////////////////////////////////////////////////////

void Widget::setMinimumSize(intsize2 minSize)
{
	m_minimumSize = minSize;
	intsize2 size = m_rect.size();

	// Adjust size when necessary
	resize(math::max(size, minSize));
}
///////////////////////////////////////////////////////////////////////////////////////////////////

void Widget::setMinimumWidth(int width)
{
	setMinimumSize(intsize2(width, minimumSize().height));
}
///////////////////////////////////////////////////////////////////////////////////////////////////

void Widget::setMinimumHeight(int height)
{
	setMinimumSize(intsize2(minimumSize().width, height));
}
///////////////////////////////////////////////////////////////////////////////////////////////////

intsize2 Widget::maximumSize() const
{
	if(m_layout)
	{
		// A widget can be configured to have a certain maximum size, however
		// sometimes children may simply require more space (for example the text
		// of a button). In order to not produce visual errors (like rendering the
		// text outside of the button) we simply overwrite the configured maximum
		// size with the minimum size reported by the style, in case the maximum size
		// is smaller).
		int4 padd = padding();
		intsize2 minSize = m_layout->calculateMinimumSize() + intsize2(padd.x + padd.z, padd.y + padd.w);
		return math::max(minSize, configuredMaximumSize());
	}
	else
	{
		return configuredMaximumSize();
	}
}
///////////////////////////////////////////////////////////////////////////////////////////////////

intsize2 Widget::configuredMaximumSize() const
{
	return m_maximumSize;
}
///////////////////////////////////////////////////////////////////////////////////////////////////

void Widget::setMaximumSize(intsize2 maxSize)
{
	m_maximumSize = maxSize;

	// Adjust size when necessary
	intsize2 size = math::min(m_rect.size(), m_maximumSize);
	resize(size);
}
///////////////////////////////////////////////////////////////////////////////////////////////////

void Widget::setMaximumWidth(int width)
{
	setMaximumSize(intsize2(width, maximumSize().height));
}
///////////////////////////////////////////////////////////////////////////////////////////////////

void Widget::setMaximumHeight(int height)
{
	setMaximumSize(intsize2(maximumSize().width, height));
}
///////////////////////////////////////////////////////////////////////////////////////////////////

int2 Widget::screenPos() const
{
	int2 pos = m_rect.topLeft;

	auto parent = m_parent.lock();
	if(parent)
		pos += parent->screenPos();

	return pos;
}
///////////////////////////////////////////////////////////////////////////////////////////////////

void Widget::setPos(const int2& pos)
{
	// Tell anyone that we've been moved
	if(m_rect.topLeft.x != pos.x || m_rect.topLeft.y != pos.y)
	{
		m_rect = math::rectangle<int>::pointSize(pos, m_rect.size());
		m_moved(m_this);
	}
}
///////////////////////////////////////////////////////////////////////////////////////////////////

void Widget::move(const int2& delta)
{
	setPos(m_rect.topLeft + delta);
}
///////////////////////////////////////////////////////////////////////////////////////////////////

void Widget::resize(intsize2 size)
{
	// We don't resize the widget to less than the minimum size
	// We don't resize the widget to more than the maximum size
	size = math::max(minimumSize(), size);
	size = math::min(maximumSize(), size);

	// Tell anyone that we've been resized.
	// (Only one component must have been changed)
	if(m_rect.size().width != size.width || m_rect.size().height != size.height)
	{
		m_rect = math::rectangle<int>::pointSize(m_rect.topLeft, size);

		// We will now entering resizing mode.
		// This means that we won't resize ourselves
		// when our child resize (endless recursion)
		m_resizing = true;
		BOOST_SCOPE_EXIT((&m_resizing))
		{
			// Just in case an exception has been thrown...
			m_resizing = false;
		}
		BOOST_SCOPE_EXIT_END

		m_resized(m_this);
	}
}
///////////////////////////////////////////////////////////////////////////////////////////////////

void Widget::setClientPos(const int2& clientPos)
{
	setPos(clientPos - padding().xy());
}
///////////////////////////////////////////////////////////////////////////////////////////////////

void Widget::setClientSize(const intsize2& clientSize)
{
	int4 padd = padding();
	resize(clientSize + intsize2(padd.x + padd.z, padd.y + padd.w));
}
///////////////////////////////////////////////////////////////////////////////////////////////////




Resizing::Type Widget::resizing() const
{
	return m_resizingType;
}
///////////////////////////////////////////////////////////////////////////////////////////////////

void Widget::setResizing(Resizing::Type type)
{
	m_resizingType = type;
}
///////////////////////////////////////////////////////////////////////////////////////////////////




bool Widget::visible() const
{
	return m_visible;
}
///////////////////////////////////////////////////////////////////////////////////////////////////

void Widget::setVisible(bool visible)
{
	m_visible = visible;
}
///////////////////////////////////////////////////////////////////////////////////////////////////




bool Widget::mouseHovered() const
{
	return m_mouseHovered;
}
///////////////////////////////////////////////////////////////////////////////////////////////////

bool Widget::mousePressed() const
{
	return m_mousePressed;
}
///////////////////////////////////////////////////////////////////////////////////////////////////

WidgetState::Type Widget::state() const
{
	return m_widgetState;
}
///////////////////////////////////////////////////////////////////////////////////////////////////




void Widget::onStateChanged(weak_ptr that)
{
	//
	// In case this widget's state has been changed, the (possibly) new color
	// and background glyph must be queried from the style, as well as the
	// minimum and maximum size of this widget.
	//
	if(!that.expired() && this == that.lock().get())
	{
		WidgetStyle::ptr widgetStyle = style();
		// Background color & glyph
		m_backgroundColor = widgetStyle->attribute<math::color>(Attributes::BackgroundColor, m_widgetState);
		m_backgroundGlyph = widgetStyle->attribute<Glyph>(Attributes::BackgroundGlyph, m_widgetState);

		// Minimum size (optional)
		intsize2 minSize = m_minimumSize;
		minSize.width = boost::numeric_cast<uint32>(widgetStyle->attribute<std::size_t>(Attributes::MinWidth,  m_widgetState, minSize.width));
		minSize.height = boost::numeric_cast<uint32>(widgetStyle->attribute<std::size_t>(Attributes::MinHeight, m_widgetState, minSize.height));
		setMinimumSize(minSize);

		// Maximum size (optional)
		intsize2 maxSize = m_maximumSize;
		maxSize.width = boost::numeric_cast<uint32>(widgetStyle->attribute<std::size_t>(Attributes::MaxWidth,  m_widgetState, maxSize.width));
		maxSize.height = boost::numeric_cast<uint32>(widgetStyle->attribute<std::size_t>(Attributes::MaxHeight, m_widgetState, maxSize.height));
		setMaximumSize(maxSize);

		// Resizing Type (optional)
		m_resizingType = widgetStyle->attribute<Resizing::Type>(Attributes::Resizing, m_widgetState, Resizing::Standard);
	}
}
///////////////////////////////////////////////////////////////////////////////////////////////////

void Widget::styleChanged()
{
	// Whenever the style has changed we signal the widget that the
	// state has changed, so that new glyphs, colors, etc... are queried
	// from the possibly new style
	m_stateChanged(m_this);
}
///////////////////////////////////////////////////////////////////////////////////////////////////

bool Widget::hitTest(const NestedState& state)
{
	if(!m_visible)
		return false;

	// Test if the mouse hovered over us and emit the
	// corresponding signal if it did. 
	if(m_rect.intersects(state.cursor().pos()))
	{
		// The mouse really does hover over us, but now we test if this should count as a hover
		// The hovered state will not be evaluated when the cursor has a widget attached to
		// that is not us (thus when resizing a window, buttons that are accidentally hovered/clicked
		// by the mouse will not really be clicked or hovered)
		if(!state.hasAttached() || state.isAttached(m_this))
			setHover(true);

		//
		// Now we test all children of this widget and see if they're being hovered/clicked
		//
		NestedState childState(state, clientPos());

		bool found = false;
		m_tmpWidgets = m_widgets;
		WidgetIterator i(m_tmpWidgets);
		while(i.hasNext())
		{
			const Widget::ptr& child = i.next();
			if(!found && child->hitTest(childState))
			{
				found = true;
			}
			else
			{
				// Once a widget reports that itself or a child is being hovered
				// the hovered flag of all remaining widgets is being set to false
				child->setHover(false);
			}
		}
	}
	else
	{
		// Sets "hovered" to false for this and ALL children of this
		setHover(false);
	}


	// As long as the mouse is pressed down and hovers over the
	// widget, we are in a pressed state.
	if(state.cursor().keyDown(Key::MouseLeft) && m_mouseHovered)
		m_mousePressed = true;

	// Once the user releases the mouse button over the widget,
	// it's a click.
	if(state.cursor().keyClicked(Key::MouseLeft) && m_mouseHovered)
		m_mouseClicked(m_this);

	if(!state.cursor().keyDown(Key::MouseLeft) || !m_mouseHovered)
		m_mousePressed = false;


	// The return status only indicates whether or not the widget is being hovered, not
	// if it has been clicked:
	return m_mouseHovered;
}
///////////////////////////////////////////////////////////////////////////////////////////////////

void Widget::update(NestedState& state)
{
	//
	// Widget State (may have changed)
	//
	// In case the state has changed, a signal must be emitted so that anyone who
	// cares can react on this. One effect is that all glyphs, colors, font descriptions,
	// etc. must be queried from the style again because it may be different for a different
	// state.
	//
	WidgetState::Type oldState = m_widgetState;

	if(m_mousePressed)      m_widgetState = WidgetState::Active;
	else if(m_mouseHovered) m_widgetState = WidgetState::Hovered;
	else                    m_widgetState = WidgetState::Normal;

	if(oldState != m_widgetState)
		m_stateChanged(m_this);


	NestedState stateForChildren(state, clientPos());

	m_tmpWidgets = m_widgets;
	WidgetIterator i(m_tmpWidgets);
	while(i.hasNext())
	{
		const Widget::ptr& child = i.next();
		child->update(stateForChildren);
	}
}
///////////////////////////////////////////////////////////////////////////////////////////////////

void Widget::processInput(QChar c)
{}
///////////////////////////////////////////////////////////////////////////////////////////////////

void Widget::render(Quads& quads, const NestedState& state)
{
	if(!visible())
		return;

	// We will only render the quad, when the alpha component
	// of the widget's background color is bigger than 0.
	if(backgroundColor().a > 0)
		renderBackground(quads, state);

#ifdef _DEBUG
	std::size_t additionalQuads = quads.size();
#endif

	renderAdditional(quads, state);

#ifdef _DEBUG
	// This test is only enabled for debug builds
	// It checks if the subclass correctly implements
	// "numAdditionalQuads()" and throws if it does not.
	additionalQuads = quads.size() - additionalQuads;
	std::size_t numAdditional = numAdditionalQuads();
	if(additionalQuads != numAdditional)
		BOOSTEXT_THROW(programming_error("A widget subclass does not return the same number of quads, it actually renders."));
#endif

	// Now that this widget is done, the children need to be rendered...
	NestedState stateForChildren(state, clientPos());

	// When rendering, we iterate over those widgets backwards, because what gets drawn last
	// stays ontop (disabled zbuffer-test): so it's a simple back-to-front rendering
	// that is necessary for alpha blending to work correctly
	WidgetIterator i(m_widgets);
	i.toBack();
	while(i.hasPrevious())
	{
		const Widget::ptr& child = i.previous();
		child->render(quads, stateForChildren);
	}
}
///////////////////////////////////////////////////////////////////////////////////////////////////

uint32 Widget::numQuads() const
{
	uint32 num = 0;

	// We don't render anything when this widget should be invisible
	if(!visible())
		return 0;

	// Currently 1 for the background
	if(backgroundColor().a > 0)
		num += 1;

	// Now whatever the actual subclass requires
	num += numAdditionalQuads();


	// Now whatever all children require
	WidgetIterator i(m_widgets);
	while(i.hasNext())
	{
		const Widget::ptr& child = i.next();
		num += child->numQuads();
	}

	return num;
}
///////////////////////////////////////////////////////////////////////////////////////////////////

void Widget::renderAdditional(Quads& quads, const NestedState& state)
{}
///////////////////////////////////////////////////////////////////////////////////////////////////

uint32 Widget::numAdditionalQuads() const
{
	return 0;
}
///////////////////////////////////////////////////////////////////////////////////////////////////




const Glyph& Widget::backgroundGlyph() const
{
	return m_backgroundGlyph;
}
///////////////////////////////////////////////////////////////////////////////////////////////////

const math::color& Widget::backgroundColor() const
{
	return m_backgroundColor;
}
///////////////////////////////////////////////////////////////////////////////////////////////////




int4 Widget::padding() const
{
	return int4(0, 0, 0, 0);
}
///////////////////////////////////////////////////////////////////////////////////////////////////

void Widget::onChildClicked(weak_ptr widget)
{
	bringToTop(widget);
}
///////////////////////////////////////////////////////////////////////////////////////////////////




void Widget::setHover(bool b)
{
	if(b)
	{
		// We're being hovered for the first time, since the mouse
		// left this widget, so this is a mouse enter event
		if(!m_mouseHovered)
			m_mouseEnter(m_this);

		// We can't conclude which child is being hovered (if any)
		// so we simply do nothing
	}
	else /*if(!b)*/
	{
		// We're being left for the first time, since the mouse
		// got over this widget, so this is a mouse enter event
		if(m_mouseHovered)
			m_mouseLeave(m_this);

		// We enforce the constraint that a child can only be hovered, if the parent is being
		// hovered as well

		m_tmpWidgets = m_widgets;
		WidgetIterator i(m_tmpWidgets);
		while(i.hasNext())
		{
			const Widget::ptr& child = i.next();
			child->setHover(false);
		}
	}

	// We actually have to change the state
	m_mouseHovered = b;
}
///////////////////////////////////////////////////////////////////////////////////////////////////

Widget::WidgetList::iterator Widget::find(const Widget::ptr& widget)
{
	WidgetList::iterator i = m_widgets.begin();

	for(i; i != m_widgets.end(); ++i)
	{
		if(widget == *i)
			break;
	}

	return i;
}
///////////////////////////////////////////////////////////////////////////////////////////////////

Widget::WidgetList::const_iterator Widget::find(const Widget::ptr& widget) const
{
	WidgetList::const_iterator i = m_widgets.constBegin();

	for(i; i != m_widgets.constEnd(); ++i)
	{
		if(widget == *i)
			break;
	}

	return i;
}
///////////////////////////////////////////////////////////////////////////////////////////////////




void Widget::renderBackground(Quads& quads, const NestedState& state) const
{
	Quad quad = backgroundGlyph().quad();
	quad.resize(clientSize());
	quad.move(state.parentPos() + clientPos());
	quad.setColor(backgroundColor());

	// The client area starts (relative to the parent) at clientPos()
	// and simply has the extends of clientSize()
	quads.push_back(quad);
}
///////////////////////////////////////////////////////////////////////////////////////////////////
